ADFA-4954 feat(kolibri): domain layer for content seeding — ids, selection, plan - #313
Draft
luisguzman-adfa wants to merge 1 commit into
Draft
ADFA-4954 feat(kolibri): domain layer for content seeding — ids, selection, plan#313luisguzman-adfa wants to merge 1 commit into
luisguzman-adfa wants to merge 1 commit into
Conversation
…ction, plan First slice of the Android side. Contracts only, per the "shared contracts land first" rule: no android.*, no HTTP, so it is unit-testable on a plain JVM and the data/service layers can be built against it. ChannelId — what counts as a usable channel or node identifier. Normalises the dashed and uppercase spellings, and rejects a Studio channel token outright: a token passed where an id is expected ends in a 404 from the downloader with no useful message, so looksLikeToken() exists purely to make the error say "that is a token, resolve it first". Same fail-closed boundary ModuleName draws for module names — an id reaches a request the box acts on. ChannelSelection — the whole channel, or named subtrees. Encodes the trap in Kolibri's API where omitting node_ids means everything and sending an empty list means nothing: the importer accepts node_ids: [] and finishes successfully having transferred zero bytes. wholeChannel() and ofSubtrees() are separate factories and ofSubtrees() refuses to produce an empty selection, including when every supplied id fails validation. Immutable, ids normalised and deduplicated, order kept. SeedPlan — what is queued and whether it fits. Answers the space question before committing to a download, which Kolibri cannot: it subtracts a 250 MB cushion when computing free space, so it can report zero with room left and only finds out mid-transfer. fitsIn() returns null for "cannot tell" rather than false, because the catalog only carries whole-channel sizes: reading an over-estimate as "does not fit" would block seeding a small subtree of a large channel, which is the case a phone needs most. 52 JVM unit tests. Verified: all six files parse; the domain imports only java.util; every method the tests call exists; JUnit 4 only, matching build.gradle. NOT COMPILED. The sandbox has no javac — no JDK, Maven Central and the Adoptium release assets are both outside the allowlist, and jdk4py ships a runtime without jdk.compiler. Type errors would not have been caught. Needs a local `gradlew :app:testDebugUnitTest` before merge.
luisguzman-adfa
marked this pull request as draft
July 31, 2026 14:13
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
First slice of the Android side of Kolibri content seeding. Contracts only, per "shared contracts land first": no android.*, no HTTP, unit-testable on a plain JVM, so the data and service layers can be built against it.
ChannelId normalises the dashed and uppercase spellings of a channel or node id and rejects a Studio token outright — a token passed as an id ends in a 404 from the downloader with no useful message, so the error says so explicitly. Same fail-closed boundary ModuleName draws for module names.
ChannelSelection separates "the whole channel" from "named subtrees", because Kolibri accepts node_ids: [] and finishes successfully having transferred zero bytes. ofSubtrees() refuses to produce an empty selection, including when every supplied id fails validation.
SeedPlan answers whether a selection fits before committing to a download. fitsIn() returns null for "cannot tell" rather than false: the catalog only carries whole-channel sizes, and reading an over-estimate as "does not fit" would block seeding a small subtree of a large channel.
52 JVM unit tests.
NOT COMPILED — the sandbox has no javac, so type errors would not have been caught. Needs
gradlew :app:testDebugUnitTestlocally before merge.